import type { Component, Ref } from 'vue'

// 控制器配置
interface UploaderConfigType {
  el: HTMLElement
  options: OptionsType
  // 视图容器
  customViewContainer?: Component
  // 自定义钩子
  hooks: UploadHooks
}

interface OptionsType {
  // 分片大小
  chunkSize: number
  // 可选择的文件类型，多个类型用英文逗号隔开
  accept: string
  // 分片队列最大并发数
  queueMax: number
  // 分片最大重试次数
  retryMax: number
  // 一次上传的最大文件大小,默认500MB
  maxTotalSize: number
  // 是否允许选择文件夹
  folder?: boolean
}

/**
 * 上传状态
 * waiting: 等待上传。
 * checkMD5: 校验MD5。
 * uploading: 分片上传。
 * merge: 分片合并。
 * retry: 重试。
 * paused: 暂停。
 * success: 成功。
 * error: 失败。
 */
type FileStatusType =
  | 'waiting'
  | 'checkMD5'
  | 'uploading'
  | 'merge'
  | 'retry'
  | 'paused'
  | 'success'
  | 'error'

// 分片对象
interface ChunkType {
  // 文件名
  fileName: string
  // 文件哈希值
  fileHash: string | unknown
  // 文件总大小
  fileSize: number
  // 分片哈希值 md5（唯一标识）
  chunkHash: string | unknown
  // 分片数据
  chunkData: Blob
  // 第几个分片
  chunkNumber: number
  // 分片大小
  chunkSize: number
  // 分片个数
  totalChunks: number
  // 上传状态
  uploaded: false | true
  // 上传进度
  progress: number
  // 上传失败次数
  retryNum: number
  // 上传开始时间
  startTime: number
}

// 文件对象
type FileObjType = {
  id: string
  fileName: string
  fileSize: number
  fileHash: string
  chunkSize: number
  fileType: string
  fileStatus: FileStatusType
  progress: number
  chunks: Blob[]
  chunkList: ChunkType[]
  fileSource: File
  startTime: number // 上传开始时间 用于计算上传速度
  uploadSpeed: string // 上传速度
  uploadedSize: number // 已上传大小
  uploadedChunks: number[] // 已上传的分片索引
  remainingTime: string // 剩余时间
}
// 日志信息接口
type LogMessage = {
  // id: string
  msg: string
  type: 'info' | 'success' | 'warning' | 'error' | 'start' | 'end'
  timestamp: Date
  time: string
}

/**
 * 队列状态
 * @param queueTaskNum 队列任务数
 * @param concurrency 并发数
 * @param runningNum 进行中数
 * @param pausedNum 已暂停数
 * @param waitingNum 等待中数
 * @param completedNum 已完成数
 * @param failedNum 失败数
 * @param chunkSize 分片大小
 * @param queueTaskTotalSize 队列任务总大小
 */

type GlobalUploadStatus = 'start' |'uploading' | 'paused' | 'end' 

type QueueStatusType = {
  queueFileNum: number // 文件数
  queueTaskNum: number // 队列任务数
  queueTaskTotalSize: number // 队列任务总大小
  runningNum: number // 当前并发池任务数
  concurrency: number // 并发请求数
  pausedFileNum: number // 已暂停文件数
  pausedTaskNum: number // 已暂停任务数
  waitingFileNum: number // 等待中文件数
  waitingTaskNum: number // 等待中任务数
  completedFileNum: number // 已完成文件数
  completedTaskNum: number // 已完成任务数
  failedFileNum: number // 失败文件数
  failedTaskNum: number // 失败任务数
  chunkSize: number // 分片大小
}

type StoreType = {
  fileList: FileObjType[]
  queueStatus: QueueStatusType
  isUpLoading: boolean
  filesTotalSize: number
}

type ViewContainerType = {
  ref: any
  maxTotalSize: number
  fileList: Ref<FileObjType[]>
  accept: string
  folder: boolean
  queueStatus: Ref<QueueStatusType>
  addFile: (files: FileList) => void

  allStart: () => void
  allPause: () => void // 暂停所有上传任务
  allResume: () => void // 恢复所有上传任务
  allDel: () => void // 重置所有上传任务

  filesTotalSize: Ref<number>
  chunkSize: number
  globalUploadStatus: Ref<GlobalUploadStatus>
  itemStart: (item: FileObjType) => void
  // 删除指定文件
  itemDel: (item: FileObjType) => void
  // 暂停指定任务组上传
  itemPause: (item: FileObjType) => void
  // 恢复指定任务组上传
  itemResume: (item: FileObjType) => void
  // 格式化文件大小
  formatFileSize: (size: number) => void
  // 格式化上传速度
  // formatUploadSpeed: (speed: number) => this.formatUploadSpeed(speed)
  // 队列状态信息
  statusEnum: any
  logs: Ref<LogMessage[]>
  // 清空日志
  clearLogs: () => void
} | {}

// 定义所有钩子函数的类型
interface UploadHooks {
  // 文件选择时触发
  onFileSelected?: (files: File[]) => boolean | Promise<any>

  // 文件格式化
  onFileChunking?: (fileItem: FileObjType) => boolean | Promise<boolean>

  // 文件哈希值计算完成
  onFileHashed?: (fileItem: FileObjType) => boolean | Promise<boolean>

  // 文件添加到上传队列后触发
  onFileAdded?: (fileItem: FileObjType) => boolean | Promise<boolean>

  // 文件分片上传成功
  onChunkUploaded?: (fileItem: FileObjType) => boolean | Promise<boolean>

  // 文件合并完成后触发
  onChunkMergeEnd?: (fileItem: FileObjType, result?: any) => boolean | Promise<boolean>

  // 所有文件上传完成后触发
  onAllComplete?: (fileItems: FileObjType[]) => boolean | Promise<boolean>

  // 检查分片是否已上传（接口调用）
  onCheckChunksByRequest?: (data: any, done: (result: any) => void) => void

  // 上传分片（接口调用）
  onUploadChunkByRequest?: (
    data: any,
    progressCallback: (progress: any) => void,
    thenCallback: (res: any) => void,
    catchCallback: (err: any) => void,
  ) => void

  // 合并分片（接口调用）
  onMergeChunkByRequest?: (data: any, done: (result: any) => void) => void
}

export type {
  OptionsType,
  FileObjType,
  UploaderConfigType,
  ChunkType,
  QueueStatusType,
  StoreType,
  FileStatusType,
  LogMessage,
  ViewContainerType,
  UploadHooks,
  GlobalUploadStatus
}
